#include "storage_manager_impl.h"
#include <mutex>
#include <sstream>
#include <iostream>
#include <thread>
#include <chrono>
#include "storage_device_impl.h"
#include "utils_log.h"
#include "common_config_manager.h"
#include "peripheral_device_monitor.h"

namespace El {
namespace Storage {

IStorageManager &IStorageManager::GetInstance()
{
    static StorageManagerImpl instance;
    return instance;
}

StorageManagerImpl::StorageManagerImpl()
{
    // 监听配置变化
    listenerId_ = Common::ConfigManager::GetInstance().Register(
        "storage",
        [this](const nlohmann::json &config) {
            EL_INFO("storage config changed: {}", config.dump().c_str());
            storageConfig_ = config;
            return true;
        },
        Common::ConfigPriority::POST_APPLY);

    // 读取配置文件
    storageConfig_ = Common::ConfigManager::GetInstance().GetConfig("/storage");
    if (!storageConfig_.empty() && storageConfig_.contains("mountPath") &&
        storageConfig_.contains("warningThreshold") && storageConfig_.contains("reserveSpace")) {
        mountPath_ = storageConfig_["mountPath"].get<std::string>();
        warningThreshold_ = storageConfig_["warningThreshold"].get<uint32_t>();
        reserveSpace_ = storageConfig_["reserveSpace"].get<uint32_t>();
    } else {
        mountPath_ = "/mnt/udisk";
        warningThreshold_ = 95;
        reserveSpace_ = 100;
        EL_ERROR("storage config is empty");
    }
    EL_INFO("storage config: mountPath {} warningThreshold {} reserveSpace {}", mountPath_, warningThreshold_,
             reserveSpace_);
}

StorageManagerImpl::~StorageManagerImpl()
{
    Stop();
    Common::ConfigManager::GetInstance().Unregister("storage", listenerId_);
}

bool StorageManagerImpl::Start()
{
    StartMonitoring();
    return true;
}

void StorageManagerImpl::Stop()
{
    StopMonitoring();
}

std::shared_ptr<IStorageDevice> StorageManagerImpl::GetDevice(std::string_view devicePath)
{
    std::lock_guard<std::mutex> lock(devicesMutex_);
    auto it = devices_.find(std::string(devicePath));
    return (it != devices_.end()) ? it->second : nullptr;
}

bool StorageManagerImpl::RemoveDevice(std::string devicePath)
{
    RemoveDeviceInternal(devicePath);
    return true;
}

StorageCapacity StorageManagerImpl::GetTotalCapacity() const
{
    std::lock_guard<std::mutex> lock(devicesMutex_);
    StorageCapacity total{};

    for (const auto &[path, device] : devices_) {
        (void)path;
        if (device->GetStatus() == DeviceStatus::ERR_MOUNTED) {
            auto capacity = device->GetCapacity();
            total.totalBytes += capacity.totalBytes;
            total.usedBytes += capacity.usedBytes;
            total.availableBytes += capacity.availableBytes;
        }
    }

    if (total.totalBytes > 0) {
        total.usagePercentage = static_cast<int32_t>(total.usedBytes * 100 / total.totalBytes);
    }

    return total;
}

bool StorageManagerImpl::CleanupSpace(uint64_t requiredBytes)
{
    (void)requiredBytes; // 避免未使用参数警告
    EL_ERROR("CleanupSpace not implemented");
    return false;
}

uint32_t StorageManagerImpl::RegisterStorageEventCallback(StorageEventCallback callback)
{
    std::lock_guard<std::mutex> lock(callbackMutex_);
    uint32_t callbackId = nextCallbackId_++;
    storageEventCallbacks_[callbackId] = std::move(callback);
    return callbackId;
}

bool StorageManagerImpl::UnregisterStorageEventCallback(uint32_t callbackId)
{
    std::lock_guard<std::mutex> lock(callbackMutex_);
    return storageEventCallbacks_.erase(callbackId) > 0;
}

void StorageManagerImpl::StartMonitoring()
{
    // 先枚举现有设备
    EnumerateExistingDevices();

    // 注册到DeviceMonitor监听block设备的热插拔事件
    auto &monitor = Peripheral::DeviceMonitor::GetInstance();
    deviceMonitorHandle_ = monitor.RegisterCallback("block",
        [this](Peripheral::DeviceEvent event, const std::string &subsystem,
               const std::string &devnode, const std::string &sysname) {
            (void)subsystem;  // 未使用
            (void)sysname;    // 未使用

            if (event == Peripheral::DeviceEvent::ADDED) {
                // 设备添加：通过DeviceMonitor枚举获取设备信息
                auto &mon = Peripheral::DeviceMonitor::GetInstance();
                mon.EnumerateDevices("block", "disk",
                    [this, &devnode](const Peripheral::DeviceInfo &deviceInfo) {
                        if (deviceInfo.devnode == devnode) {
                            DeviceType deviceType = DetectDeviceType(deviceInfo.properties, deviceInfo.devnode);
                            if (deviceType != DeviceType::ERR_UNKNOWN) {
                                AddAndMountDevice(deviceInfo.devnode, deviceType);
                            }
                        }
                    });
            } else if (event == Peripheral::DeviceEvent::REMOVED) {
                // 设备移除
                RemoveDeviceInternal(devnode);
            }

            // 检查容量警告
            CheckCapacityWarnings();
        });

    // 启动或合并监控子系统，确保包含 "block"
    monitor.Start({"block"});

    // 启动容量监控定时器，每秒检查一次存储容量
    capacityMonitorTimer_.start(1000, [this]() {
        CheckCapacityWarnings();
    });

    EL_INFO("Storage monitoring started using DeviceMonitor");
}

void StorageManagerImpl::StopMonitoring()
{
    // 停止容量监控定时器
    capacityMonitorTimer_.stop();

    // 注销回调
    if (deviceMonitorHandle_ >= 0) {
        auto &monitor = Peripheral::DeviceMonitor::GetInstance();
        monitor.UnregisterCallback(deviceMonitorHandle_);
        deviceMonitorHandle_ = -1;
    }

    EL_INFO("Storage monitoring stopped");
}

void StorageManagerImpl::CheckCapacityWarnings()
{
    std::lock_guard<std::mutex> lock(devicesMutex_);

    for (const auto &[path, device] : devices_) {
        (void)path;
        if (device->GetStatus() != DeviceStatus::ERR_MOUNTED) {
            continue;
        }

        auto capacity = device->GetCapacity();
        uint64_t availableMB = capacity.availableBytes / (1024 * 1024);
        if (availableMB <= (reserveSpace_ + 100)) {
            EL_DEBUG("Storage space warning: device {} available {}MB below reserve {}MB", device->GetDevicePath(),
                      availableMB, (reserveSpace_ + 100));
            NotifyStorageEvent(device, DeviceStatus::ERR_CAPACITY_WARNING);
        }

        bool isFull = false;
        if (availableMB <= reserveSpace_) {
            EL_DEBUG("Storage space full: device {} available {}MB below reserve {}MB", device->GetDevicePath(),
                      availableMB, reserveSpace_);
            NotifyStorageEvent(device, DeviceStatus::ERR_CAPACITY_FULL);
            isFull = true;
        }

        const std::string devicePath = device->GetDevicePath();
        bool wasInWarningState = deviceWarningStates_[devicePath];

        if (!isFull && wasInWarningState) {
            EL_DEBUG("Storage space returned to normal: device {} available {}MB above reserve {}MB",
                      device->GetDevicePath(), availableMB, reserveSpace_);
            NotifyStorageEvent(device, DeviceStatus::ERR_CAPACITY_NORMAL);
        }

        deviceWarningStates_[devicePath] = isFull;
    }
}

void StorageManagerImpl::EnumerateExistingDevices()
{
    auto &monitor = Peripheral::DeviceMonitor::GetInstance();
    monitor.EnumerateDevices("block", "disk",
        [this](const Peripheral::DeviceInfo &deviceInfo) {
            DeviceType deviceType = DetectDeviceType(deviceInfo.properties, deviceInfo.devnode);
            if (deviceType != DeviceType::ERR_UNKNOWN && !deviceInfo.devnode.empty()) {
                AddAndMountDevice(deviceInfo.devnode, deviceType);
            }
        });
}

void StorageManagerImpl::NotifyStorageEvent(const std::shared_ptr<IStorageDevice> &device, DeviceStatus status)
{
    EL_DEBUG("NotifyStorageEvent: {} {}", device->GetDevicePath(), static_cast<int>(status));
    std::lock_guard<std::mutex> lock(callbackMutex_);
    for (const auto &[id, callback] : storageEventCallbacks_) {
        (void)id;
        if (callback) {
            callback(device, status);
        }
    }
}

DeviceType StorageManagerImpl::DetectDeviceType(const std::map<std::string, std::string> &properties,
                                                 const std::string &devnode)
{
    if (devnode.empty()) {
        return DeviceType::ERR_UNKNOWN;
    }

    // 获取关键属性
    auto getBus = [&properties]() -> std::string {
        auto it = properties.find("ID_BUS");
        return (it != properties.end()) ? it->second : "";
    };

    auto getType = [&properties]() -> std::string {
        auto it = properties.find("ID_TYPE");
        return (it != properties.end()) ? it->second : "";
    };

    auto getPath = [&properties]() -> std::string {
        auto it = properties.find("ID_PATH");
        return (it != properties.end()) ? it->second : "";
    };

    std::string idBus = getBus();
    std::string idType = getType();
    std::string idPath = getPath();

    // 打印调试信息
    EL_DEBUG("Device detection - Path: {}, Bus: {}, Type: {}", devnode, idBus, idType);

    // 检查设备名称是否包含mmcblk
    if (devnode.find("mmcblk") != std::string::npos) {
        // mmcblk0通常是eMMC，其他是SD卡
        if (devnode.find("mmcblk0") != std::string::npos) {
            EL_INFO("Detected eMMC device: {}", devnode);
            return DeviceType::EMMC_NAND;
        } else {
            EL_INFO("Detected SD card: {}", devnode);
            return DeviceType::SD_CARD;
        }
    }

    // SD卡检测 (通过总线类型)
    if (idBus == "mmc") {
        // 检查是否为内置eMMC (通过路径判断)
        if (!idPath.empty() && idPath.find("platform-") != std::string::npos) {
            EL_INFO("Detected eMMC device: {}", devnode);
            return DeviceType::EMMC_NAND;
        }
        EL_INFO("Detected SD card: {}", devnode);
        return DeviceType::SD_CARD;
    }

    // USB存储设备检测
    if (idBus == "usb") {
        EL_INFO("Detected USB drive: {}", devnode);
        return DeviceType::USB_DRIVE;
    }

    EL_DEBUG("Unknown device type: {}", devnode);
    return DeviceType::ERR_UNKNOWN;
}

bool StorageManagerImpl::AddAndMountDevice(const std::string &devpath, DeviceType deviceType)
{
    auto device = StorageDeviceImpl::CreateStorageDevice(deviceType, devpath, mountPath_);
    if (!device) {
        EL_ERROR("Failed to create storage device for {}", devpath);
        return false;
    }

    {
        std::lock_guard<std::mutex> lock(devicesMutex_);
        devices_[devpath] = device;
        deviceWarningStates_[devpath] = false; // 初始化为非警告状态
    }

    NotifyStorageEvent(device, DeviceStatus::ERR_DEVICE_ADDED);

    if (device->Mount()) {
        NotifyStorageEvent(device, DeviceStatus::ERR_MOUNTED);
        return true;
    }

    EL_ERROR("Failed to mount device {}", devpath);
    return false;
}

void StorageManagerImpl::RemoveDeviceInternal(const std::string &devpath)
{
    auto device = GetDevice(devpath);
    if (!device) {
        EL_ERROR("Device not found: {}", devpath);
        return;
    }

    // 先发送设备移除事件,让上层模块(如录像)立即停止使用设备
    // 这样可以避免在设备物理移除后仍尝试写入文件
    NotifyStorageEvent(device, DeviceStatus::ERR_DEVICE_REMOVED);
    EL_INFO("Device removed notification sent: {}", devpath);

    // 给上层模块一点时间停止使用设备
    std::this_thread::sleep_for(std::chrono::milliseconds(200));

    // 再尝试卸载设备(可能失败,因为设备可能已物理移除)
    device->Unmount();
    NotifyStorageEvent(device, DeviceStatus::ERR_UNMOUNTED);
    EL_INFO("Device unmounted: {}", devpath);

    // 从设备列表中移除
    {
        std::lock_guard<std::mutex> lock(devicesMutex_);
        devices_.erase(devpath);
        deviceWarningStates_.erase(devpath); // 清理警告状态
    }
}

bool StorageManagerImpl::GetDefaultUdiskStatus(DeviceStatus &status)
{
    std::lock_guard<std::mutex> lock(devicesMutex_);

    // 遍历所有设备，查找USB_DRIVE类型的设备
    for (const auto &[path, device] : devices_) {
        (void)path;
        if (device) {
            status = device->GetStatus();
            return true;
        }
    }

    // 如果没有找到USB设备，返回NOT_EXIST状态
    status = DeviceStatus::ERR_NOT_EXIST;
    return false;
}

} // namespace Storage
} // namespace El
